package com.starlink.common.scheduled;

import com.starlink.common.enums.OrderTypeEnum;
import com.starlink.model.domain.*;
import com.starlink.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.starlink.common.enums.BooleanEnum.FALSE;
import static com.starlink.common.enums.OrderStatusEnum.WAIT_PAY;

/**
 * @author: zyh
 * @date: 2024-05-05
 */
@Slf4j
@Service
public class WechatScheduledTask {
    @Autowired
    private MallOrderService bookOrderService;
    @Autowired
    private MallOrderDetailsService booksOrderDetailsService;
    @Autowired
    private MallBooksSpecificationService booksSpecificationService;

    @Autowired
    private MallPeripheryOrderService peripheryOrderService;
    @Autowired
    private MallPeripheryOrderDetailsService peripheryOrderDetailsService;
    @Autowired
    private MallPeripherySpecificationService peripherySpecificationService;

    @Autowired
    private ShoppingCartOrderService cartOrderService;
    @Autowired
    private ShoppingCartOrderDetailsService shoppingCartOrderDetailsService;

    @Autowired
    private UserService userService;

    /**
     * 订单支付超时取消
     */
    @Scheduled(cron = "0 */1 * * * ?")
    @Transactional(rollbackFor = Exception.class)
    public void ordertimeout() {
        //查询书籍超时未支付订单
        List<MallBooksOrderDO> bookOrderList = bookOrderService.lambdaQuery()
                .lt(MallBooksOrderDO::getTimeout, LocalDateTime.now())
                .eq(MallBooksOrderDO::getStatus, WAIT_PAY.getType().toString())
                .last("FOR UPDATE")
                .list();
        if (CollectionUtils.isNotEmpty(bookOrderList)){
            List<Long> bookOrderIds = bookOrderList.stream().map(MallBooksOrderDO::getId).collect(Collectors.toList());
            List<MallBooksOrderDetailsDO> mallBooksOrderDetailsDOS = booksOrderDetailsService.lambdaQuery()
                    .in(MallBooksOrderDetailsDO::getMallBooksOrderId, bookOrderIds)
                    .last("FOR UPDATE")
                    .list();
            if (CollectionUtils.isNotEmpty(mallBooksOrderDetailsDOS)){
                mallBooksOrderDetailsDOS.forEach(orderDetailDO->{
                    Long specificationId = orderDetailDO.getSpecificationId();
                    Long quantity = orderDetailDO.getQuantity();
                    Map<String, Long> map = new HashMap<>();
                    map.put("specificationId",specificationId);
                    map.put("quantity",quantity);
                    //恢复库存
                    booksSpecificationService.addQuantity(map);
                });
            }
            String stringIds = buildStringIds(bookOrderIds);
            bookOrderService.deleteDOByIds(stringIds);
            booksOrderDetailsService.deletedByOrderIds(stringIds);
        }

        //查询周边超时未支付订单
        List<MallPeripheryOrderDO> peripheryOrderDOS = peripheryOrderService.lambdaQuery()
                .lt(MallPeripheryOrderDO::getTimeout, LocalDateTime.now())
                .eq(MallPeripheryOrderDO::getStatus, WAIT_PAY.getType().toString())
                .last("FOR UPDATE")
                .list();
        if (CollectionUtils.isNotEmpty(peripheryOrderDOS)){
            List<Long> ids = peripheryOrderDOS.stream().map(MallPeripheryOrderDO::getId).collect(Collectors.toList());
            List<MallPeripheryOrderDetailsDO> peripheryOrderDetailsDOS = peripheryOrderDetailsService.lambdaQuery()
                    .in(MallPeripheryOrderDetailsDO::getMallPeripheryOrderId, ids)
                    .last("FOR UPDATE")
                    .list();
            if (CollectionUtils.isNotEmpty(peripheryOrderDetailsDOS)){
                peripheryOrderDetailsDOS.forEach(orderDetailDO->{
                    Long specificationId = orderDetailDO.getSpecificationId();
                    Long quantity = orderDetailDO.getQuantity();
                    Map<String, Long> map = new HashMap<>();
                    map.put("specificationId",specificationId);
                    map.put("quantity",quantity);
                    //恢复库存
                    peripherySpecificationService.addQuantity(map);
                });
            }
            String stringIds = buildStringIds(ids);
            peripheryOrderService.deleteDOByIds(stringIds);
            peripheryOrderDetailsService.deletedByOrderIds(stringIds);
        }

        //查询购物车超时未支付订单
        List<ShoppingCartOrderDO> cartOrderDOS = cartOrderService.lambdaQuery()
                .lt(ShoppingCartOrderDO::getTimeout, LocalDateTime.now())
                .eq(ShoppingCartOrderDO::getStatus, WAIT_PAY.getType().toString())
                .last("FOR UPDATE")
                .list();
        if (CollectionUtils.isNotEmpty(cartOrderDOS)){
            List<Long> ids = cartOrderDOS.stream().map(ShoppingCartOrderDO::getId).collect(Collectors.toList());
            List<ShoppingCartOrderDetailsDO> cartOrderDetailsDOS = shoppingCartOrderDetailsService.lambdaQuery()
                    .in(ShoppingCartOrderDetailsDO::getShoppingCartOrderId, ids)
                    .last("FOR UPDATE")
                    .list();
            if (CollectionUtils.isNotEmpty(cartOrderDetailsDOS)){
                cartOrderDetailsDOS.forEach(orderDetailDO->{
                    Integer articlesCategory = orderDetailDO.getArticlesCategory();
                    Long specificationId = orderDetailDO.getSpecificationId();
                    Long quantity = orderDetailDO.getQuantity();
                    Map<String, Long> map = new HashMap<>();
                    map.put("specificationId",specificationId);
                    map.put("quantity",quantity);
                    //恢复库存
                    if (OrderTypeEnum.BOOK.getType().equals(articlesCategory)){
                        booksSpecificationService.addQuantity(map);
                    }else if (OrderTypeEnum.RIM.getType().equals(articlesCategory)){
                        peripherySpecificationService.addQuantity(map);
                    }
                });
            }
            String stringIds = buildStringIds(ids);
            cartOrderService.deleteDOByIds(stringIds);
            shoppingCartOrderDetailsService.deletedByOrderIds(stringIds);
        }
    }

    private static String buildStringIds(List<Long> ids){
        StringBuilder idStr = new StringBuilder();
        ids.forEach(id->{
            idStr.append(id).append(",");
        });
        return idStr.deleteCharAt(idStr.length()-1).toString();
    }

    /**
     * VIP到期取消 每半小时执行一次
     */
    @Scheduled(cron = "0 0/30 * * * ?")
    @Transactional(rollbackFor = Exception.class)
    public void vipExpire() {
        //查询所有过期的用户
        List<UserDO> list = userService.lambdaQuery()
                .lt(UserDO::getVipExpireDate, LocalDateTime.now())
                .list();
        if (CollectionUtils.isNotEmpty(list)){
            List<Long> userIds = list.stream().map(UserDO::getId).collect(Collectors.toList());
            userService.lambdaUpdate()
                    .set(UserDO::getVip,FALSE.getCode())
                    .set(UserDO::getUpdateTime,new Date())
                    .in(UserDO::getId,userIds)
                    .update();
        }
    }
}
